package com.joelemon.mockinfluxdbdata.mock;

import cn.hutool.core.date.DateField;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import com.joelemon.mockinfluxdbdata.common.SystemException;
import com.joelemon.mockinfluxdbdata.datamock.v1.ObjectModelMockConfig;
import com.joelemon.mockinfluxdbdata.enums.InsertType;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;

/**
 * @Description: 差值策略
 * @Author: HJY
 * @Date: 2023/11/14
 */
@Data
public class InsertStrategy {

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private DateTime start;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    private DateTime end;

    private Long nextRunningTime;

    private Long intervalMS;

    // 批处理量级
    private Integer batchNum;

    public List<DateTime> getTimes() {
        check();
        DateTime now = new DateTime();
        if (start != null && start.isAfter(now)
                || (end != null && end.after(now))) return null;
        if (nextRunningTime != null && intervalMS != null) {
            DateTime nextTime = new DateTime(nextRunningTime);
            if (nextTime.isAfter(now)) return null;
            if (end != null) return getTimesBetween(nextTime, end);
            return getTimesBetween(nextTime, now);
        }
        if (start == null && (end == null || (end != null && end.isAfter(now)))) {
            nextRunningTime = now.getTime() + intervalMS;
            return Arrays.asList(now);
        }
        if (start != null && intervalMS != null) {
            if (end == null) return getTimesBetween(start, now);
            return getTimesBetween(start, end);
        }
        return null;
    }

    private void check() {
        if (batchNum != null && batchNum < 1) {
            throw new SystemException("插入配置异常（批量数据数要大于0）" + this);
        }
        if (intervalMS != null && intervalMS < 0) {
            throw new SystemException("插入配置异常（时间间隔存在且要大于0）" + this);
        }
    }

    private List<DateTime> getTimesBetween(DateTime start, DateTime end) {
        List<DateTime> dateTimes = null;
        if (batchNum != null) {
            long batchEndMS = start.getTime() + intervalMS * (batchNum - 1);
            if (batchEndMS < end.getTime()) {
                dateTimes = DateUtil.rangeToList(start, new DateTime(batchEndMS), DateField.MILLISECOND, intervalMS.intValue());
            } else {
                dateTimes = DateUtil.rangeToList(start, end, DateField.MILLISECOND, intervalMS.intValue());
            }
        } else {
            dateTimes = DateUtil.rangeToList(start, end, DateField.MILLISECOND, intervalMS.intValue());
        }
        // 更新下次执行
        if (CollectionUtils.isNotEmpty(dateTimes)) {
            nextRunningTime = dateTimes.get(dateTimes.size() - 1).getTime() + intervalMS;
        }
        return dateTimes;
    }

    public Long needDalaySeconds() {
        DateTime now = new DateTime();
        if (nextRunningTime != null) {
            if (nextRunningTime > now.getTime())
                return (nextRunningTime - now.getTime()) / 1000;
            return 0L;
        }
        if (start != null && start.isAfter(now))
            return (start.getTime() - now.getTime()) / 1000;
        if (nextRunningTime == null && start != null && start.isBefore(now)) return 0L;
        return intervalMS / 1000;
    }
}
